/**
	Pulsar engine. Core.
	Additional include file. String operations: advanced formatting

	Copyright (C) 2013-2014 Dmitry Dolgov

	This program is free software; you can redistribute it and/or modify it under the terms of the
	GNU General Public License as published by the Free Software Foundation; either version 2 of
	the License, or (at your option) any later version.

	This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
	without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
	See the GNU General Public License for more details.
*/

namespace pl
{

// Internal data: align options
enum _Align
{
	_ALIGN_LEFT,
	_ALIGN_RIGHT,
	_ALIGN_CENTER
};

// Internal data: output struct
struct _Options
{
	pl_char fillChar;
	pl_uint8 radix;
	pl_uint16 size;
	pl_uint8 decPoint;
	pl_uint8 align;
};

/**
	Advanced formatting class with safety instructions

	Usage formatting string:
	%%# (%%0, %%1, etc) - substitute << operands
	%%[options]# - additional formatting
	Options are:
		size:use N characters to output next field
		align:{left|center|right}
		fill:letter to fill align (by default: space)
		dec:use N digit for floating point values
		radix:# use decomal, ocatl, hexdecimal or binary output
	Examples:
		%%[size:30,align:left]

	Max 10 substitutions allowed
*/
template<pl_uint32 N> class StringFormat
{
public:
	// ctor
	StringFormat(String<N>& str) :
	_str(str),
	_pos(0)
	{
	}

	template<typename T> StringFormat& operator << (const T &value)
	{
		if (_str.size() < 3)
		{
			PL_ASSERTW(FALSE, PL_T("Format String to small"));
			return *this;
		}
		if (_pos >= 10)
		{
			PL_ASSERTW(FALSE, PL_T("Maximum 10 substitution allowed"));
			return *this;
		}

		// Looking for the next place to formatting
		_Options opt;
		pl_uint32 replacement;
		pl_uint32 pos = _findSubst(_str.get(), _pos++, opt, replacement);
		if (pos >= _str.size())
		{
			PL_ASSERTW(FALSE, PL_T("%%<num> substitution not found"));
			return *this;
		}

		// Perform substitution
		String<N> s;
		s << value;
		_str.replace(pos, replacement, s);
		return *this;
	}

private:

	String<N>& _str;   // Internal buffer
	pl_uint32 _pos;    // Position in internal buffer

	StringFormat &operator = (const StringFormat&)
	{
	}
};

/*
	Aux function
	format("Sample %%0") << 100;
*/
template<pl_uint32 N> StringFormat<N> format(String<N>& str)
{
	return StringFormat<N>(str);
}

// For internal usage only
extern pl_uint32 _findSubst(const pl_char* str, pl_uint32 pos, _Options& opt, pl_uint32& replacement);

} // namespace pl

//
// End of file 'pulsar_string_format.h'
//
